import { Server } from 'http'
import { Server as SocketServer } from 'socket.io'
import { redis } from '../redis'
import { Jackpot, PrizePoolRecord, SystemConfig } from './db'

/**
 * 当前的游戏状态
 */
interface State {
    /**
     * 最近轮次的数据
     */
    trends: Round[]
    /**
     * 开关
     */
    flags: Record<string, string>
    /**
     * 本小时开奖时间
     */
    minutes: {
        time: string
        gift_price: number
    }[]
}

/**
 * 最近轮次的数据
 */
interface Round {
    time: string
    gift_price: number
    balance: number
    in: number
    out: number
}

let state: State

function parseRound(round: string) {
    const year = parseInt(round.substring(0, 4))
    const month = parseInt(round.substring(4, 6))
    const day = parseInt(round.substring(6, 8))
    const hour = parseInt(round.substring(8, 10))
    const minute = parseInt(round.substring(10))

    return Date.UTC(year, month - 1, day, hour, minute)
}

/**
 * 返回趋势数据
 * @returns
 */
async function getTrends(): Promise<Round[]> {
    const balanceRow = await Jackpot.findOne()
    let balance = balanceRow!.balance

    const rounds = await PrizePoolRecord.findAll({
        order: [['id', 'DESC']],
        limit: 30,
    })

    return rounds.map((round) => {
        const round_balance = balance.toNumber()
        const delta = round.buy_amount_all.sub(round.gift_price_all).sub(round.commission)
        balance = balance.sub(delta)

        return {
            time: round.game_round.substring(8, 10) + ':' + round.game_round.substring(10),
            balance: round_balance,
            gift_price: round.gift_price.toNumber(),
            in: round.buy_amount_all.toNumber(),
            out: round.gift_price_all.add(round.commission).toNumber(),
        }
    })
}

/**
 * 返回开关数据
 */
async function getFlags(): Promise<Record<string, string>> {
    return SystemConfig.getValue('xyc_o1', 'xyc_o2')
}

const PRIZE_POOL = [11, 13, 23, 26]

/**
 * 返回开奖时间
 */
async function getMinutes(): Promise<
    {
        time: string
        gift_price: number
    }[]
> {
    const cache = await redis.get('xyc_grand_prize')
    if (!cache) {
        return []
    }

    const rawData = JSON.parse(JSON.parse(cache))

    return (rawData.minutes ?? []).map((minute: string) => {
        return {
            time: `${rawData.hour}:${minute.padStart(2, '0')}`,
            gift_price: PRIZE_POOL[parseInt(minute) % 4],
        }
    })
}

/**
 * 刷新状态
 */
async function refreshState(): Promise<State> {
    const [trends, flags, minutes] = await Promise.all([getTrends(), getFlags(), getMinutes()])
    return {
        trends,
        flags,
        minutes,
    }
}

export default function createXycServer(socketServer: SocketServer, server: Server) {
    socketServer.on('connection', (socket) => {
        socket.on('xyc:get_state', async () => {
            if (!state) {
                state = await refreshState()
            }
            socket.emit('xyc:state', state)
        })

        socket.on('xyc:set_flag', async (name: string, value: string) => {
            await SystemConfig.update({ value }, { where: { menu_name: name } })
            if (state) {
                state.flags[name] = value
                socketServer.emit('xyc:state', state)
            }
        })
    })

    setInterval(async () => {
        state = await refreshState()
        socketServer.emit('xyc:state', state)
    }, 15000)
}
